package org.apitool.main;

import java.io.BufferedReader;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.UnsupportedEncodingException;
import java.net.URL;
import java.net.URLDecoder;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.log4j.Logger;
import org.mortbay.jetty.Handler;
import org.mortbay.jetty.Request;
import org.mortbay.jetty.Server;
import org.mortbay.jetty.handler.AbstractHandler;
import org.mortbay.jetty.handler.DefaultHandler;
import org.mortbay.jetty.handler.HandlerList;
import org.mortbay.jetty.handler.ResourceHandler;
import org.mortbay.jetty.servlet.Context;
import org.mozilla.javascript.ScriptableObject;
import org.quartz.Scheduler;

import com.alibaba.fastjson.JSONObject;

/**
 * Hello world!
 * 
 */
/**
 * 
 * <b>类名称：</b>Main<br/>
 * <b>类描述：</b>
 * 
 * <pre>
 </pre>
 * 
 * <br/>
 * <b>创建人：</b>张军强<br/>
 * <b>修改人：</b>张军强<br/>
 * <b>修改时间：</b>2013-4-24 上午9:34:42<br/>
 * <b>修改备注：</b><br/>
 * 
 * @version 1.0.0<br/>
 */
public class Main {

	private static final Logger logger = Logger.getLogger(Main.class.getName());

	public static ApiServlet api = new ApiServlet();

	private static Scheduler scheduler = null;

	private static String consumerkey = "A2i1ee5iofqkf43f3Ts0X";
	private static String consumerSecret = "Q4ux5qRH9GaH8tVwDCwInLy6z8snR";
	public static boolean isDebug = false;
	public static String username = "appadmin";
	public static String pwd = "appadmin111";
	public static String user_sn = "040ABG49FTS3";
	public static String login_type = "client";
	public static String conf = "";
	public static String header = "{'app-version':'2.1.1'}";
	public static ScriptableObject scope;
	public static org.mozilla.javascript.Context cx;
	// private static String consumerKey = "";
	// private static String consumerSecret = "";
	private static String LOCATION = null;

	public static String email = "{'host':'smtp.163.com','user':'easyphp','pwd':'123456','from':'easyphp@163.com'}";
	public static String jdbc = "{'host':'127.0.0.1','user':'root','pwd':'root','db':'monitor','port':3306}";
	static {
		try {
			LOCATION = URLDecoder.decode(Main.class.getProtectionDomain().getCodeSource().getLocation().getFile(), "UTF-8");
		} catch (UnsupportedEncodingException e) {
			LOCATION = "";
		}
	}

	public static String getProjectPath() throws UnsupportedEncodingException {

		URL url = Main.class.getProtectionDomain().getCodeSource().getLocation();

		String filePath = URLDecoder.decode(url.getPath(), "utf-8");

		if (filePath.endsWith(".jar")) {

			filePath = filePath.substring(0, filePath.lastIndexOf("/") + 1);

		}

		File file = new File(filePath);

		filePath = file.getAbsolutePath();

		return filePath;

	}

	public static void addJob() {

	}
	
	public static String ping(String host){
		 String line = null;
       try
       {
           Pattern pat=Pattern.compile("((?:\\d+\\.){3}\\d+)[\\s\\S]+(ttl)",Pattern.CASE_INSENSITIVE);
           		
       	Process pro = Runtime.getRuntime().exec("ping "+host );
           BufferedReader buf = new BufferedReader(new InputStreamReader(pro.getInputStream()));
           while((line = buf.readLine()) != null) {
          	 
             Matcher m = pat.matcher(line);
             while(m.find()){ 
           	  return m.group(0);
             }
                 
           }
       }
       catch(Exception ex)
       {
           System.out.println(ex.getMessage());
       }
       return "";
	}

	public static class RedirectHandler extends AbstractHandler {

		private static String getFile(String filename) throws IOException {

			File file = new File(filename);

			FileInputStream ins = new FileInputStream(file);
			ByteArrayOutputStream os = new ByteArrayOutputStream();
			int len = 0;
			byte[] b = new byte[1024];
			while ((len = ins.read(b)) > 0) {
				os.write(b, 0, len);
			}
			return os.toString("utf-8");

		}

		private static String getFile(InputStream input) throws IOException {

			ByteArrayOutputStream os = new ByteArrayOutputStream();
			int len = 0;
			byte[] b = new byte[1024];
			while ((len = input.read(b)) > 0) {
				os.write(b, 0, len);
			}
			return os.toString("utf-8");

		}

		public void handle(String target, HttpServletRequest request, HttpServletResponse response, int dispatch) throws IOException, ServletException {
			try {
				response.setContentType("text/html;charset=UTF-8");
				String host = request.getParameter("__host");
				String basepath = "/org/apitool/web/resources";
				if (target.toLowerCase().startsWith("/js/")) {
					response.setHeader("Expires", "0");
					response.setContentType("text/html;charset=UTF-8");
					// System.out.println(basepath + target);
					response.getWriter().write(getFile(Main.class.getResourceAsStream(basepath + target)));
					response.getWriter().flush();
					response.setStatus(HttpServletResponse.SC_OK);
					((Request) request).setHandled(true);
					// response.getWriter().close();

				}else if (target.toLowerCase().startsWith("/systemping/")) {
					
					String thost= host.replaceAll("http(s)?://", "");
					String ipinfo= ping( host.replaceAll("http(s)?://", ""));
					
					response.getWriter().write(thost+"\t"+ipinfo); 
					response.setStatus(HttpServletResponse.SC_OK);
					((Request) request).setHandled(true);

				} else if (target.toLowerCase().startsWith("/systemmonitor/")) {
					response.setContentType("text/html;charset=UTF-8");
					String ret = "";
					if (request.getParameter("action").equals("add")) {
						ret = "以下RUL启动监控\n";
						ret = ret + MonitorManager.getInstance().addJob(request.getParameter("apis"), host, request.getParameter("email"));

					} else if (request.getParameter("action").equals("del")) {
						ret = "以下RUL停止监控\n";
						ret = ret + MonitorManager.getInstance().delJob(request.getParameter("apis"), host, request.getParameter("email"));
					}

					response.getWriter().write(ret);
					response.setStatus(HttpServletResponse.SC_OK);
					((Request) request).setHandled(true);

				} else if (target.toLowerCase().startsWith("/systemtest/")) {

					String projectPath = getProjectPath();
					String filename = projectPath + "/conf/assert.js";

					if (!Main.conf.equals("")) {
						filename = Main.conf + "/conf/assert.js";
					}

					String assertjs = getFile(filename);

					try {
						cx = org.mozilla.javascript.Context.enter();
						scope = cx.initStandardObjects();
						cx.evaluateString(scope, assertjs, "assert.js", 1, null);
					} catch (Exception e) {
						e.printStackTrace();
					}
					Map apis = JSONObject.parseObject(request.getParameter("apis") == null ? "{}" : request.getParameter("apis").toString(), Map.class);
					response.setContentType("text/html;charset=UTF-8");
					Iterator it = apis.keySet().iterator();
					StringBuffer builder = new StringBuffer();
					while (it.hasNext()) {
						List<Map> arrayApi = JSONObject.parseArray(apis.get(it.next()).toString(), Map.class);
						for (int i = 0; arrayApi != null && i < arrayApi.size(); i++) {
							Map test = JSONObject.parseObject(arrayApi.get(i).get("test") == null ? "{}" : arrayApi.get(i).get("test").toString(), Map.class);
							Map requestMap = JSONObject.parseObject(arrayApi.get(i).get("request").toString(), Map.class);
							Map paramMap = JSONObject.parseObject(requestMap.get("param").toString(), Map.class);
							if (Boolean.parseBoolean(test.get("autoTest") == null ? "false" : test.get("autoTest").toString())) {
								String ret = api.getBase().post(host + requestMap.get("url").toString(), paramMap);
								Map assertMap = (Map) arrayApi.get(i).get("assert");
								String rule = assertMap.get("rule").toString();
								String expect = assertMap.get("expect").toString();
								Object obj = scope.callMethod(scope, rule, new Object[] { ret, expect });
								if (obj.equals(true)) {
									response.getWriter().write(requestMap.get("url").toString());
									response.getWriter().write("\tpass");
									response.getWriter().write("\t" + arrayApi.get(i).get("desc").toString() + "\n");
								} else {
									response.getWriter().write(requestMap.get("url").toString());
									response.getWriter().write("\terror");
									response.getWriter().write("\t" + arrayApi.get(i).get("desc").toString() + "\n");
								}
							} else {
								builder.append(requestMap.get("url").toString());
								builder.append("\tunknow\t" + arrayApi.get(i).get("desc").toString() + "\n");
							}
						}
					}
					response.getWriter().write(builder.toString());

					response.setStatus(HttpServletResponse.SC_OK);
					((Request) request).setHandled(true);

				} else if (target.toLowerCase().startsWith("/conf/")) {
					String projectPath = getProjectPath();

					response.setContentType("text/html;charset=UTF-8");

					String filename = projectPath + target;
					if (!Main.conf.equals("")) {
						filename = Main.conf + target;
					}

					response.getWriter().write(getFile(filename));
					response.getWriter().flush();
					response.setStatus(HttpServletResponse.SC_OK);
					((Request) request).setHandled(true);

				} else if (target.toLowerCase().startsWith("/systemsetting/")) { 

					try {
						Map map = (Map) JSONObject.parse(request.getParameter("setting"));
						String username = map.get("username") == null ? Main.username : map.get("username").toString();
						Main.login_type = map.get("loginType") == null ? Main.login_type : map.get("loginType").toString();
						String pwd = map.get("pwd") == null ? Main.pwd : map.get("pwd").toString();
						String sn = map.get("sn") == null ? Main.user_sn : map.get("sn").toString();
						String consumerkey = map.get("consumerkey") == null ? Main.consumerkey : map.get("consumerkey").toString();
						String consumerSecret = map.get("consumerSecret") == null ? Main.consumerSecret : map.get("consumerSecret").toString();
						Main.header = map.get("header") == null ? Main.header : map.get("header").toString();
						Main.email = map.get("email") == null ? Main.email : map.get("email").toString();
						TestBase base = new TestBase(consumerkey, consumerSecret, username, pwd, sn);
						String cookie = map.get("cookie") == null ? "" : map.get("cookie").toString();
						host = host.replaceAll("http[s]?://", "");
						base.getClient().setCookie(host, cookie);
						response.getWriter().write("set successfull!");

						if (base.login(Main.login_type, username, pwd, sn)) {
							response.setContentType("text/html;charset=UTF-8");

							api.setBase(base);

							// response.getWriter().write("set successfull!");
							response.getWriter().flush();
							response.setStatus(HttpServletResponse.SC_OK);
							((Request) request).setHandled(true);

						} else {
							response.setContentType("text/html;charset=UTF-8");

							// response.getWriter().write("set fail!");
							response.getWriter().flush();
							response.setStatus(HttpServletResponse.SC_OK);
							((Request) request).setHandled(true);

						}

					} catch (Exception e) {
						response.setContentType("text/html;charset=UTF-8");

						response.getWriter().write("set fail!");
						response.getWriter().flush();
						response.setStatus(HttpServletResponse.SC_OK);
						((Request) request).setHandled(true);
					}

				} else if (target.equalsIgnoreCase("/") || target.equalsIgnoreCase("/index.html")) {

					response.setContentType("text/html;charset=UTF-8");
					response.getWriter().write(getFile(Main.class.getResourceAsStream("/org/apitool/web/resources/index.html")));
					response.setStatus(HttpServletResponse.SC_OK);
					((Request) request).setHandled(true);
				} else {
					response.setContentType("text/html;charset=UTF-8");

					try {
						api.doPost(request, response);

					} catch (Exception e) {
						e.printStackTrace(response.getWriter());
						response.getWriter().flush();
						response.setStatus(HttpServletResponse.SC_NOT_FOUND);
						((Request) request).setHandled(true);

					}

				}
			} catch (Exception e) {
				try {
					e.printStackTrace(response.getWriter());
					response.getWriter().flush();
					((Request) request).setHandled(true);
				} catch (Exception ee) {
					ee.printStackTrace();
				}
			}
		}
	}

	public static String getFile(String filename) throws IOException {

		File file = new File(filename);

		FileInputStream ins = new FileInputStream(file);
		ByteArrayOutputStream os = new ByteArrayOutputStream();
		int len = 0;
		byte[] b = new byte[1024];
		while ((len = ins.read(b)) > 0) {
			os.write(b, 0, len);
		}
		return os.toString("utf-8");

	}

	private static String getFile(InputStream input) throws IOException {

		ByteArrayOutputStream os = new ByteArrayOutputStream();
		int len = 0;
		byte[] b = new byte[1024];
		while ((len = input.read(b)) > 0) {
			os.write(b, 0, len);
		}
		return os.toString("utf-8");

	}

	public static void initScriptEngier() {

		// cx = org.mozilla.javascript.Context.enter();
		// scope = cx.initStandardObjects();

	}

	public static Object parseJson(Object jsonStr, String key) {
		Object obj = null;
		if (jsonStr instanceof String) {
			obj = JSONObject.parseObject(jsonStr.toString());
		} else if (jsonStr instanceof JSONObject) {
			obj = jsonStr;
		} else {
			obj = JSONObject.parseObject(jsonStr.toString());
		}
		String[] keys = key.split("\\-\\>");
		int len = 0;
		while (len < keys.length) {
			if (obj instanceof JSONObject) {
				obj = ((JSONObject) obj).get(keys[len]);
			}
			len++;
		}
		return obj;
	}

	public static void main(String[] args) throws Exception {

		int port = 8081;

		String username = "appadmin";
		String pwd = "appadmin111";
		String sn = "M81B08BJCBP030186";

		int len = args.length;
		int pos = 0;
		while (pos < len) {
			if (args[pos].equals("-port")) {
				port = Integer.valueOf(args[++pos]);
			} else if (args[pos].equals("-key")) {
				consumerkey = args[++pos];
			} else if (args[pos].equals("-secret")) {
				consumerSecret = args[++pos];
			} else if (args[pos].equals("-u") || args[pos].equals("-username")) {
				username = args[++pos];
			} else if (args[pos].equals("-password")) {
				pwd = args[++pos];
			} else if (args[pos].equals("-sn")) {
				sn = args[++pos];
			} else if (args[pos].equals("-debug")) {
				isDebug = Boolean.parseBoolean(args[++pos]);
			} else if (args[pos].equals("-conf")) {
				conf = args[++pos];
			} else if (args[pos].equals("-header")) {
				header = args[++pos];
			} else if (args[pos].equals("-jdbc")) {
				header = args[++pos];
			} else if (args[pos].equals("-jdbc")) {
				jdbc = args[++pos];
			} else if (args[pos].equals("-h") || args[pos].equals("-help")) {
				help();
				System.exit(0);
			} else {
				++pos;
			}
		}

		Server server = new Server(port);

		initScriptEngier();

		ResourceHandler fileHandler = new ResourceHandler();
		fileHandler.setResourceBase("..");
		Context context = new Context(server, "/", Context.SESSIONS);
		// ApiServlet api = new ApiServlet();
		// context.addServlet(new ServletHolder(api), "/api");
		// context.addServlet(new ServletHolder(api), "/service/");

		TestBase base = new TestBase(consumerkey, consumerSecret, username, pwd, sn);
		api.setBase(base);

		HandlerList handlers = new HandlerList();
		handlers.setHandlers(new Handler[] { new RedirectHandler(), fileHandler, context, new DefaultHandler() });
		server.setHandler(handlers);

		server.start();
		server.join();

	}

	/**
	 * <b>创建人：</b>张军强<br/>
	 * help<br/>
	 * <b>方法描述：</b> <br/>
	 * void
	 * 
	 * @exception
	 * @since 1.0.0
	 */

	private static void help() {

		StringBuilder builder = new StringBuilder();
		builder.append(" -port 8081 \r\n");
		builder.append(" -key A2i1ee5iofqkf43f3Ts0X \r\n");
		builder.append(" -secret Q4ux5qRH9GaH8tVwDCwInLy6z8snR \r\n");
		builder.append(" -username appadmin \r\n");
		builder.append(" -password appadmin111 \r\n");
		builder.append(" -sn M81B08BJCBP030186 \r\n");
		builder.append(" -debug false \r\n");
		builder.append(" -header  \"{'app-version':'2.1.1'}\" \r\n");

		System.out.println(builder.toString());

	}

}
